\indent Este filtro consiste en transformar cada pixel en una relaci\'on 1-a-1 con la imagen procesada pero retocando los pixels en base a su valor original. Dados par\'ametros de entrada $max$, $min$ y $Q$, se determina el valor de cada pixel de salida seg\'un esta sea menor que $min$, mayor que $max$ o cualquier otro caso.
\indent La idea del algoritmo ser\'a entonces recorrer la matriz formada por la imagen fuente de a 16 bytes, determinar en que caso cae el pixel de la imagen fuente, determinar el nuevo valor (que ser\'a 0, 255 o el resultado de una funci\'on) y asignarlo a la imagen final. 



\subsubsection{Carga de datos}

\indent Se comienza guardando los punteros a la imagen fuente en $r12$ y destino en $r13$. En $xmm1$ armamos una m\'ascara con los valores del par\'ametro $max$ que luego voy a usar para comparar. 
\begin{center}
\xmmxWord{$max$}{$max$}{$max$}{$max$}{$max$}{$max$}{$max$}{$max$}
\end{center}
\indent Notar que puede que tengamos que multiplicar el valor de cada pixel por $Q$, por ende \'este resultado podr\'ia no entrar en 1 byte, de modo que vamos a tener que hacer un unpack para que cada pixel use 2 bytes en vez de 1 y asi asegurarnos que no perdemos informaci\'on. Como dijimos que en cada iteraci\'on queriamos procesar 1 pixels, vamos a usar la t\'ecnica de loop unrolling para procesar primero 8 bytes y luego los restantes 8.
\indent Se crea la m\'ascara para el par\'ametro $min$ en $xmm2$
\begin{center}
\xmmxWord{$min$}{$min$}{$min$}{$min$}{$min$}{$min$}{$min$}{$min$}
\end{center}
\indent El registro $r15$ va a tener guardado el ancho de cada fila para ir comparando cuando se termina cada una. Se asigna a $rdi$ el valor de $r12$ que representa la matriz fuente, y a $rsi$ el valor de $r13$ que es la matriz destino. Finalmente, se asigna a $rcx$ la cantidad de columnas que se van a procesar dividido 16 (usando la instrucci\'on $shr$), puesto que cada iteraci\'on va a procesar 16 pixels.
\indent Con los registros inicializados se puede comenzar con la iteraci\'on del ciclo principal.


\subsubsection{Ciclo Principal}
\begin{itemize}
\item Se chequea si se terminaron de procesar las columnas ($rcx = 0$) para pasar a procesar los bytes sueltos de la fila (aquellos remanentes por no ser m\'ultiplo de 16 la cantidad de columnas)
\item Se copian los 16 pixels a procesar al registro $xmm4$ y $xmm5$ :
\begin{center}
\xmmxByteHighBig{$P_{8}$}{$P_{9}$}{$P_{10}$}{$P_{11}$}{$P_{12}$}{$P_{13}$}{$P_{14}$}{$P_{15}$}\xmmxByteLowBig{$P_{0}$}{$P_{1}$}{$P_{2}$}{$P_{3}$}{$P_{4}$}{$P_{5}$}{$P_{6}$}{$P_{7}$}
\end{center}
\item Se extiende a word cada uno tomando la parte baja y alta respectivamente. Por ej, $xmm4$ :
\begin{center}
\xmmxWord{$P_{0_{l}}$}{$P_{1_{l}}$}{$P_{2_{l}}$}{$P_{3_{l}}$}{$P_{4_{l}}$}{$P_{5_{l}}$}{$P_{6_{l}}$}{$P_{7_{l}}$}
\end{center}
\item Se toma $Q$ y se arman 4 floats en $xmm8$, quedando : 
\begin{center}
\xmmxDWord{$Q$}{$Q$}{$Q$}{$Q$}
\end{center}
\item Dado que en $xmm4$ y $xmm5$ tenemos n\'umeros en words y los $Q$ son floats, hay que pasar los 8 enteros de $xmm4$ y $xmm5$ a floats, usando las instrucciones $punpcklbw$ (parte baja), $punpckhbw$ (parte alta) y $cvtdq2ps$ para finalmente pasar a floats en $xmm9$ y $xmm10$ lo que antes estaba como word en $xmm4$ y $xmm5$ respectivamente.
\item Se divide por $Q$, quedando por ejemplo $xmm9$ :
\begin{center}
\xmmxDWord{$P1/Q$}{$P2/Q$}{$P3/Q$}{$P4/Q$}
\end{center}
\item El resultado de cada operaci\'on de divisi\'on hay que truncarlo al entero menor, usando la instrucci\'on $cvttps2dq$ tanto para $xmm9$ como para $xmm10$. Asi por ejemplo, $xmm9$ queda como:
\begin{center}
\xmmxDWord{$\lfloor P1/Q \rfloor$}{$\lfloor P2/Q \rfloor$}{$\lfloor P3/Q \rfloor$}{$\lfloor P4/Q \rfloor$}
\end{center}
\item Se convierte a float nuevamente pues tenemos que multiplicar por $Q$. Lo hacemos, al igual que antes, con la instrucci\'on $cvtdq2ps$, tanto para $xmm9$ como para $xmm10$
\item Se multiplica por $Q$, que se hab\'ia guardado en $xmm8$ anteriormente, tanto $xmm9$ como $xmm10$. Quedando por ejemplo $xmm9$ :
\begin{center}
\xmmxDWord{$\lfloor P1/Q \rfloor * Q$}{$\lfloor P2/Q \rfloor * Q$}{$\lfloor P3/Q \rfloor * Q$}{$\lfloor P4/Q \rfloor * Q$}
\end{center}
\item Se convierte a float nuevamente pues tenemos que multiplicar por $Q$. Lo hacemos, al igual que antes, con la instrucci\'on $cvtdq2ps$ 
\item Nos queda volver a convertir a entero (pu\'es los pixels destino son enteros, no float) usando la instrucci\'on $cvttps2dq$.
\item Finalmente se empaquetan los resultados obtenidos en $xmm9$ y $xmm10$ para formar los primeros 8 bytes procesados con la funci\'on.
\item Como dijimos antes, por la t\'ecnica de loop unrolling, se repite el mismo proceso para los 8 pixels restantes.
\item Una vez terminado de procesar los \'ultimos 8 bytes, se vuelven a empaquetar los resultados parciales para tener los 16 pixels procesados con la funci\'on especificada. Asi $xmm9$ queda con los 16 pixels procesados. Cabe destacar que estos pixeles no necesariamente van a ser parte de la imagen final, lo ser\'an dependiendo del valor de cada pixel original.
\item En este punto se tiene en $xmm9$ los pixels procesados con la funci\'on (tercer caso de la funci\'on $I_{out}$), $xmm1$ tiene una m\'ascara con el par\'ametro $max$ y lo propio para $min$ en $xmm2$. Ahora solo resta hacer las comparaciones para ver que valores hay que asignar a cada pixel en la imagen destino.
\item Se toman los pixels originales en $xmm4$ y $xmm5$ y se comparan contra $max$ (esta en $xmm1$), empaquetando el resultado en $xmm6$
\item Se repite la operaci\'on anterior pero esta vez comparando con el valor $min$.
\item Se toman los pixels originales y se comparan byte a byte con los valores $max$, usando la instrucci\'on $pcmpeqb xmm15, xmm3$
\item Se sacan aquellos iguales al m\'inimo, usando $por xmm13, xmm15$
\item Se agregan al resultado aquellos correspondientes a la operaci\'on aritm\'etica
\item Y finalmente se guarda el resultado en $[rsi]$
\item Luego queda por chequear los avances para los pr\'oximos pixels
\begin{itemize}
\item Mover $rdi$ y $rsi$ 16 bytes hacia adelante
\item Restamos 1 a $rci$ que es el contador de columnas por procesar
\end{itemize}
\item Finalmente nos ocupamos del padding segun corresponda (en la etiqueta $chequeoBytesSueltos$) y el c\'odigo necesario para avanzar a la siguiente fila.
\end{itemize}
\indent 














